package soap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.util.Iterator;

/**
 * Created by Administrator on 2017/4/29.
 *
 * http://blog.csdn.net/qq_24505127/article/details/53057099   博客网址
 */
public class test {
	/**
	 * 通过httpClient发送soap报文
	 * @param requestSoap 请求报文
	 * @param serviceAddress 请求地址
	 * @param charSet 字符集
	 * @param contentType 返回的contentType
	 * @return 响应报文
	 * @throws WebServiceModuleRuntimeException
	 */
	public String sendRequestSoap(String requestSoap, String serviceAddress, String charSet, String contentType)
			throws WebServiceModuleRuntimeException {
		String resultSoap = "";
		PostMethod postMethod = new PostMethod(serviceAddress);
		byte[] b = new byte[0];
		try {
			b = requestSoap.getBytes(charSet);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		InputStream is = new ByteArrayInputStream(b, 0, b.length);
		RequestEntity re = new InputStreamRequestEntity(is, b.length, contentType);
		postMethod.setRequestEntity(re);

		HttpClient httpClient = new HttpClient();
		int statusCode = 0;
		try {
			statusCode = httpClient.executeMethod(postMethod);
			System.out.println("statusCode = " + statusCode);
		} catch (IOException e) {
			throw new WebServiceModuleRuntimeException("执行http请求失败", e);
		}
		if (statusCode == 200) {
			try {
				resultSoap = postMethod.getResponseBodyAsString();
			} catch (IOException e) {
				throw new WebServiceModuleRuntimeException("获取请求返回报文失败", e);
			}
		} else {
			throw new WebServiceModuleRuntimeException("请求失败：" + statusCode);
		}

		return resultSoap;
	}
	public static void main(String []args){
		StringBuilder sb=new StringBuilder(); //构造请求报文
//		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?> ");
		sb.append("<XML>");
		sb.append("<ns1:PODDLY xmlns:ns1=\"http://sec.com/GLS_ECC_LE/LEM\"> ");
		sb.append("<MessageSenderIdentifier>C630DQ0W</MessageSenderIdentifier>");
		sb.append("<MessageSenderName>SINOTRANS</MessageSenderName>");
		sb.append("<MessageReceiverIdentifier>C6NO</MessageReceiverIdentifier>");
		sb.append("<MessageReceiverName>SCIC</MessageReceiverName>");
		sb.append("<MessageTypeIdentifier>PODDLY</MessageTypeIdentifier>");
		sb.append("<MessageName>PROOF OF DELIVERY</MessageName>");
		sb.append("<MessageNumber>PDGZ8372441996-01-20170425101734</MessageNumber>");
		sb.append("<MessageFunctionCode>9</MessageFunctionCode>");
		sb.append("<DocumentNumber>PDGZ8372441996-01</DocumentNumber>");
		sb.append("<DocumentDate>20170425</DocumentDate>");
		sb.append("<ActualPODDate>20170424</ActualPODDate>");
		sb.append("<ActualPODTime>101600</ActualPODTime>");

		sb.append("<PODType>  ");
		sb.append("<Code>POD</Code>  ");
		sb.append("<CodeDescription>Normal POD</CodeDescription>  ");
		sb.append("</PODType>  ");

		sb.append("<BusinessType>  ");
		sb.append("<Code>LD</Code>  ");
		sb.append("</BusinessType>  ");

		sb.append("<OrderType>  ");
		sb.append("<Code>O10</Code>  ");
		sb.append("<CodeDescription>普通出库</CodeDescription>  ");
		sb.append("</OrderType>  ");

		sb.append("<ServiceType>  ");
		sb.append("<Code>NORM</Code>  ");
		sb.append("</ServiceType>  ");

		sb.append("<TransportationType>  ");
		sb.append("<Code>T1</Code>  ");
		sb.append("</TransportationType>  ");

		sb.append("<RelatedDocument>  ");
		sb.append("<Code>642</Code>  ");
		sb.append("</RelatedDocument>  ");

		sb.append("<RelatedDocumentNumber>  ");
		sb.append("<RelatedMessageNumber>642</RelatedMessageNumber>  ");
		sb.append("<RelatedDocumentNumber>642</RelatedDocumentNumber>  ");
		sb.append("<RelatedDocumentDate>642</RelatedDocumentDate>  ");
		sb.append("</RelatedDocumentNumber>  ");

		sb.append("<Division>  ");
		sb.append("<Code>A1</Code>  ");
		sb.append("</Division>  ");

		sb.append("<SalesOrganization>  ");
		sb.append("<Code>6302</Code>  ");
		sb.append("</SalesOrganization>  ");

		sb.append("<RefList>  ");
		sb.append("<RefItem>  ");
		sb.append("<SequenceNumber>1</SequenceNumber>  ");
		sb.append("<ReferenceDocument>  ");
		sb.append("<Code>642</Code>  ");
		sb.append("</ReferenceDocument>  ");
		sb.append("<ReferenceDocumentNumber>  ");
		sb.append("<ReferenceDocumentNumber>8372441996</ReferenceDocumentNumber>  ");
		sb.append("<ReferenceDate>20170419</ReferenceDate>  ");
		sb.append("</ReferenceDocumentNumber>  ");
		sb.append("</RefItem>  ");
		sb.append("</RefList>  ");

		sb.append("<TotalCargoInformation>  ");
		sb.append("<Quantity>30</Quantity>  ");
		sb.append("<QuantityCode>PC</QuantityCode>  ");
		sb.append("<Volume>3.78</Volume>  ");
		sb.append("<VolumeCode>M3</VolumeCode>  ");
		sb.append("<GrossWeight>348</GrossWeight>  ");
		sb.append("<GrossWeightCode>KG</GrossWeightCode>  ");
		sb.append("<NetWeight>0</NetWeight>  ");
		sb.append("<NetWeightCode>KG</NetWeightCode>  ");
		sb.append("</TotalCargoInformation>  ");

		sb.append("<OrgItem>  ");
		sb.append("<SequenceNumber>5</SequenceNumber>  ");
		sb.append("<RelatedOrganization>  ");
		sb.append("<Type>WE</Type>  ");
		sb.append("<TypeName>Ship-to party</TypeName>  ");
		sb.append("<Name>顺丰海口区仓储配送仓库</Name>  ");
		sb.append("<Address>570100海南省海口市琼山区顺达路17号</Address>  ");
		sb.append("<Address>莫兴瓦</Address>  ");
		sb.append("<Address>CN</Address>  ");
		sb.append("<TelephoneNumber>86-13876371607</TelephoneNumber>  ");
		sb.append("<Code>0008226201</Code>  ");
		sb.append("</RelatedOrganization>  ");
		sb.append("<Field1>570100</Field1>  ");
		sb.append("</OrgItem>  ");

		sb.append("<LocList>  ");
		sb.append("<LocItem>  ");
		sb.append("<SequenceNumber>1</SequenceNumber>  ");
		sb.append("<RoutingInformation>  ");
		sb.append("<Type>6TA</Type>  ");
		sb.append("<TypeName>PICKUP_PLACE</TypeName>  ");
		sb.append("<CountryCode>CN</CountryCode>  ");
		sb.append("<CountryName>China</CountryName>  ");
		sb.append("<CityOrPortName>WC01</CityOrPortName>  ");
		sb.append("</RoutingInformation>  ");
		sb.append("</LocItem>  ");
		sb.append("<LocItem>  ");
		sb.append("<SequenceNumber>2</SequenceNumber>  ");
		sb.append("<RoutingInformation>  ");
		sb.append("<Type>20</Type>  ");
		sb.append("<TypeName>FINAL DESTINATION</TypeName>  ");
		sb.append("<CountryCode>CN</CountryCode>  ");
		sb.append("<CountryName>China</CountryName>  ");
		sb.append("<RegionCode>570100</RegionCode>  ");
		sb.append("<PostalCode>570100</PostalCode>  ");
		sb.append("</RoutingInformation>  ");
		sb.append("</LocItem>  ");
		sb.append("</LocList>  ");

		sb.append("<TrkList>  ");
		sb.append("<TrkItem>  ");
		sb.append("<SequenceNumber>1</SequenceNumber>  ");
		sb.append("<TruckCntrClassification>0001</TruckCntrClassification>  ");
		sb.append("<TruckCntrNumber>  ");
		sb.append("<Number>粤AC5962</Number>  ");
		sb.append("<Type>TNM07.6</Type>  ");
		sb.append("</TruckCntrNumber>  ");
		sb.append("<TruckRound>1</TruckRound>  ");
		sb.append("<ConsolidationNumber>M8372441996</ConsolidationNumber>  ");
		sb.append("<ConsolidationCount>1</ConsolidationCount>  ");
		sb.append("<Material>UA40KU6300JXXZ</Material>  ");
		sb.append("<UnitTransportationType>  ");
		sb.append("<Code>T1</Code>  ");
		sb.append("</UnitTransportationType>  ");
		sb.append("<CargoInformation>  ");
		sb.append("<Quantity>30</Quantity>  ");
		sb.append("<QuantityCode>PC</QuantityCode>  ");
		sb.append("</CargoInformation>  ");
		sb.append("</TrkItem>  ");
		sb.append("</TrkList>  ");

		sb.append("<MatList>  ");
		sb.append("<MatItem>  ");
		sb.append("<SequenceNumber>1</SequenceNumber>  ");
		sb.append("<AccidentReason>  ");
		sb.append("<Code>NOR</Code>  ");
		sb.append("</AccidentReason>  ");

		sb.append("<Material>  ");
		sb.append("<Material>UA40KU6300JXXZ</Material>  ");
		sb.append("<GoodsDescription>LED TV,UA40KU6300J,40,CHINA,UWP60/U40KP</GoodsDescription>  ");
		sb.append("<ItemNumber>000010</ItemNumber>  ");
		sb.append("<BuyerMaterial>UA40KU6300JXXZ</BuyerMaterial>  ");
		sb.append("</Material>  ");
		sb.append("<Plant>  ");
		sb.append("<Code>S613</Code>  ");
		sb.append("</Plant>  ");
		sb.append("<StorageLocation>  ");
		sb.append("<Code>WCO1</Code>  ");
		sb.append("</StorageLocation>  ");
		sb.append("<Grade>A</Grade>  ");
		sb.append("<CargoInformation>  ");
		sb.append("<Quantity>30</Quantity>  ");
		sb.append("<QuantityCode>PC</QuantityCode>  ");
		sb.append("<Volume>3.78</Volume>  ");
		sb.append("<VolumeCode>M3</VolumeCode>  ");
		sb.append("<GrossWeight>348</GrossWeight>  ");
		sb.append("<GrossWeightCode>KG</GrossWeightCode>  ");
		sb.append("</CargoInformation>  ");
		sb.append("</MatItem>  ");
		sb.append("</MatList>  ");
		sb.append("</XML>");
		String requestSoap=sb.toString();
		String responseSoap = "";
		try{
			responseSoap = new test().sendRequestSoap(requestSoap,"http://192.168.1.100:8888/findObj?id=78a7cad7-69cf-4eb9-a760-79919bc8fc18","utf-8","text/xml; charset=utf-8");
			System.out.println(new test().parseResponseSoap("result_code", "", responseSoap));
		}catch (WebServiceModuleRuntimeException ex){
			try {
				throw new ModuleException("发动请求失败",ex);
			} catch (ModuleException e) {
				e.printStackTrace();
			}
		}


	}
	/**
	 * 解析返回报文
	 * @param node 标记所在节点
	 * @param attr 标记所在属性
	 * @param soap 报文
	 * @return 标记值
	 * @throws WebServiceModuleRuntimeException
	 */
	public String parseResponseSoap(String node, String attr, String soap) throws WebServiceModuleRuntimeException {
		//然后用SOAPMessage 和 SOAPBody
		Document personDoc;
		try {
			personDoc = new SAXReader().read(new StringReader(soap));
			Element rootElt = personDoc.getRootElement(); // 获取根节点
			Iterator body = rootElt.elementIterator("Body");
			while (body.hasNext()) {
				Element recordEless = (Element) body.next();
				return nextSubElement(node,attr,recordEless);
			}
		} catch (DocumentException e) {
			throw new WebServiceModuleRuntimeException("解析返回报文失败", e);
		}
		return "";
	}
	/**
	 * 递归方法，查找本节点是否有标记信息，如果没有就查找下一层，
	 * 在下一层里同样查找本层节点，只要找到值，就层层返回。
	 * @param node 节点标签名
	 * @param attr 节点属性值
	 * @param el 当前节点对象
	 * @return 目标值
	 */
	public static String nextSubElement(String node, String attr, Element el) {
		if (el.getName().equals(node)) {
			//说明 找到了目标节点
			//属性值为空说明取标签内容
			if (attr.equals("")) {
				Iterator sub2 = el.elementIterator();
				//有子节点说明标签内容不是单一值，需要拿到查询结果
				if (sub2.hasNext()) {
					while (sub2.hasNext()) {
						Element s2 = (Element) sub2.next();
						//如果返回的不是单一的标记值，而是查询结果，有些麻烦，
						//查询结果应当是list<map>格式，但是map的key值不好确定，是标签名作为key还是属性值作为key
						//todo
					}
				} else {
					return  el.getText();
				}

			} else {
				Attribute attrbute = el.attribute(attr);
				return attrbute.getText();
			}
		} else {
			Iterator sub2 = el.elementIterator();
			while (sub2.hasNext()) {
				Element sub = (Element) sub2.next();
				return nextSubElement(node, attr, sub);
			}
		}
		return "";
	}
}
